package user

import (
	"crypto/md5"
	"encoding/hex"
	"encoding/json"
	"net/http"

	library "../library"
	HTTP "../library/http"
	protocol "../library/httplib/protocol"
	Key "../library/key"
)

// User 用户路由
//  路由接口
// 	   Path			定义路由前戳
//     Path/GetKey     		得到Cache的Key
//     Path/UserHeartBeat	User 心跳包
//     Path/CacheHeartBeat  Cache 心跳包
//     Path/Login  			登陆
//     Path/LoggedOut  		退出登陆
type User struct {
	Path     string      // 路由前戳
	Handle   *HTTP.HTTP  // 路由对象
	DataBase *library.DB // 用户数据库
	// Key
	cacheKey *Key.Key // 缓存Key
	userKey  *Key.Key // 用户管理
}

// New 创建
func (U *User) New() error {
	//---------------------------
	// 创建用户表
	if _, err := U.DataBase.GetDB().Exec(`CREATE TABLE IF NOT EXISTS "User"("ID" TEXT, "User" TEXT,"Password" TEXT);`); err != nil {
		return err
	}
	// 创建路由表
	if _, err := U.DataBase.GetDB().Exec(`CREATE TABLE IF NOT EXISTS "Protocol"("ID" TEXT,"Path" TEXT,"Privilege" TEXT);`); err != nil {
		return err
	}
	//---------------------------
	// 数据库 DB
	DB := U.DataBase.GetDB()
	// 缓存使用 Key
	U.cacheKey = new(Key.Key)
	U.cacheKey.Init()
	// 登陆使用 Key
	U.userKey = new(Key.Key)
	U.userKey.Init()
	//--------------------------- 认证Key/用户心跳包/缓存心跳包
	// GetKey 得到访问 Key
	//	用于登陆使用
	//	得到一个 Key 而Key由登陆接口验证
	GetKey := &protocol.Protocol{
		Path:         U.Path + `/GetKey`,
		RegExp:       false,
		ProtocolType: "POST",
		// 处理过程
		Processor: func(w http.ResponseWriter, r *http.Request, v map[string]interface{}) {
			// 创建认证
			key, uuid := U.cacheKey.Add()
			key.LifeCycle = 300 // 设置Key超时 5分钟
			// 返回对象
			data, _ := json.Marshal(struct{ Key string }{Key: uuid})
			// 发送到前端
			w.Write(data)
		},
	}
	// 允许跨域
	GetKeyHandle := GetKey.Routing()
	GetKeyHandle.CrossDomain = true
	U.Handle.Handle[GetKeyHandle] = GetKey
	// UserHeartBeat 心跳包
	UserHeartBeat := &protocol.Protocol{
		Path:         U.Path + `/UserHeartBeat`,
		RegExp:       false,
		UsingKey:     true,
		Key:          U.userKey,
		ProtocolType: "POST",
		// 处理过程
		Processor: func(w http.ResponseWriter, r *http.Request, v map[string]interface{}) {
			// 得到目标对象
			if Info, ok := U.userKey.IfKey(v, "Key"); ok {
				(*Info).LifeCycle = 300
				w.Write([]byte("Ok"))
				return
			}
			w.Write([]byte("NO"))
		},
	}
	// 允许跨域
	UserHeartBeatHandle := UserHeartBeat.Routing()
	UserHeartBeatHandle.CrossDomain = true
	U.Handle.Handle[UserHeartBeatHandle] = UserHeartBeat
	// CacheHeartBeat 心跳包
	CacheHeartBeat := &protocol.Protocol{
		Path:         U.Path + `/CacheHeartBeat`,
		RegExp:       false,
		UsingKey:     true,
		Key:          U.cacheKey,
		ProtocolType: "POST",
		// 处理过程
		Processor: func(w http.ResponseWriter, r *http.Request, v map[string]interface{}) {
			// 得到目标对象
			if Info, ok := U.cacheKey.IfKey(v, "Key"); ok {
				(*Info).LifeCycle = 300
				w.Write([]byte("Ok"))
				return
			}
			w.Write([]byte("NO"))
		},
	}
	// 允许跨域
	CacheHeartBeatHandle := CacheHeartBeat.Routing()
	CacheHeartBeatHandle.CrossDomain = true
	U.Handle.Handle[CacheHeartBeatHandle] = CacheHeartBeat
	//--------------------------- 登陆/退出
	// MD5生成
	MD5 := func(text string) string {
		ctx := md5.New()
		ctx.Write([]byte(text))
		return hex.EncodeToString(ctx.Sum(nil))
	}
	// Login 登陆
	login := &protocol.Protocol{
		Path:         U.Path + `/Login`,
		RegExp:       false,
		Key:          U.cacheKey,
		UsingKey:     true,
		ProtocolType: "POST",
		// 处理过程
		Processor: func(w http.ResponseWriter, r *http.Request, v map[string]interface{}) {
			// 销毁 Key
			KeyStr, _ := v["Key"].(string)
			// 返回数据
			Return := struct {
				Key    string `json:"Key"`   // 返回Key
				Errors string `json:"Error"` // 错误信息
			}{}
			defer func() {
				// 转换 json
				data, _ := json.Marshal(Return)
				// 发送到前端
				w.Write(data)
			}()
			// 验证参数
			var User string
			var Password string
			if user, ok := v["User"]; ok {
				User, ok = user.(string)
				if !ok {
					Return.Errors = "用户名异常"
					return
				}
			}
			if password, ok := v["Password"]; ok {
				Password, ok = password.(string)
				if !ok {
					Return.Errors = "密码异常"
					return
				}
			}
			if User == "" || Password == "" {
				Return.Errors = "用户名/密码/Key不可为空"
				return
			}
			//-------------------------------------------------------------------------
			// 查询用户信息
			rows, err := DB.Query(`select  ID,Password  from User where User=?;`, User)
			if err != nil {
				Return.Errors = err.Error()
				return
			}
			defer rows.Close() // 关闭
			//	获得结果
			for rows.Next() {
				var (
					id       string
					password string
				)
				err := rows.Scan(&id, &password)
				if err != nil {
					Return.Errors = err.Error()
					return
				}
				// 处理用户信息
				if Password == MD5(KeyStr+password) {
					// 创建认证
					key, uuid := U.userKey.Add()
					key.Key = id
					key.LifeCycle = 300
					// 设置认证
					Return.Key = uuid
					// 得到权限
					ProtocolRows, err := DB.Query(`select Path,Privilege from Protocol where ID=?;`, id)
					if err != nil {
						Return.Errors = err.Error()
						return
					}
					defer ProtocolRows.Close()
					for ProtocolRows.Next() {
						var (
							Path      string
							Privilege string
						)
						err := ProtocolRows.Scan(&Path, &Privilege)
						if err != nil {
							Return.Errors = err.Error()
							return
						}
						// 得到路由权限
						key.Privilege[Path] = Privilege == "true"
					}
				} else {
					Return.Errors = "密码错误"
				}
				return
			}
			Return.Errors = "用户名不存在"
		},
	}
	// 允许跨域
	LoginHandle := login.Routing()
	LoginHandle.CrossDomain = true
	U.Handle.Handle[LoginHandle] = login
	// LoggedOut 用户退出
	LoggedOut := &protocol.Protocol{
		Path:         U.Path + `/LoggedOut`,
		RegExp:       false,
		Key:          U.userKey,
		UsingKey:     true,
		ProtocolType: "POST",
		// 处理过程
		Processor: func(w http.ResponseWriter, r *http.Request, v map[string]interface{}) {
			U.userKey.Delete(v["Key"].(string))
			w.Write([]byte("OK"))
		},
	}
	// 允许跨域
	LoggedOutHandle := LoggedOut.Routing()
	LoggedOutHandle.CrossDomain = true
	U.Handle.Handle[LoggedOutHandle] = LoggedOut
	return nil
}

// GetCache 用于缓冲使用的Key没有用户登陆功能
func (U *User) GetCache() *Key.Key {
	return U.cacheKey
}

// GetUser 用户Key用于登陆用户使用
func (U *User) GetUser() *Key.Key {
	return U.userKey
}
